package com.sun.stringescapeutils.impl;

import com.sun.dao.entity.SmsEntity;
import com.sun.stringescapeutils.SmsFilter;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class FrequencyFilter implements SmsFilter {

    /**
     * 发送间隔, 单位: 毫秒
     */
    private long sendInterval;
    private ConcurrentMap<String,Long> sendAddressMap = new ConcurrentHashMap<>();

    /**
     *定期清理sendAddressMap
     */
    private long cleanMapInterval;
    private Timer timer = new Timer("sms_frequency_filter_clear_data_thread");

    @Override
    public void init(){
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                cleanSendAddressMap();
            }
        },cleanMapInterval,cleanMapInterval);
    }

    @Override
    public boolean filter(SmsEntity smsEntity) {
        if(setSendTime(smsEntity.getMobile()) && setSendTime(smsEntity.getIp())){
            return true;
        }
        return false;
    }

    @Override
    public void destroy() {
        timer.cancel();
    }

    /**
     * 将发送时间修改为当前时间.
     * 如果距离上次发送的时间间隔大于{@link #sendInterval}则设置发送时间为当前时间. 否则不修改任何内容.
     *
     * @param id 发送手机号 或 ip
     * @return 如果成功将发送时间修改为当前时间, 则返回true. 否则返回false
     */
    private boolean setSendTime(String id) {
        long currentTime = System.currentTimeMillis();

        /*putIfAbsent
        如果传入key对应的value已经存在，就返回存在的value，不进行替换。
        如果不存在，就添加key和value，返回null*/
        Long sendTime = sendAddressMap.putIfAbsent(id, currentTime);
        if(sendTime == null) {
            return true;
        }

        long nextCanSendTime = sendTime + sendInterval;
        if(currentTime < nextCanSendTime) {
            return false;
        }

        if(sendAddressMap.replace(id, sendTime, currentTime)) {
            return true;
        }

        return sendAddressMap.putIfAbsent(id,currentTime)==null;
    }

    /**
     * 将sendAddressMap中的所有过期数据删除
     */
    private void cleanSendAddressMap() {
        long currentTime = System.currentTimeMillis();
        long expireSendTime = currentTime - sendInterval;

        for(String key : sendAddressMap.keySet()) {
            Long sendTime = sendAddressMap.get(key);
            if(sendTime < expireSendTime) {
                sendAddressMap.remove(key, sendTime);
            }
        }


    }
}
